#include "stdafx.h"
#include "processlog.h"
#include "standard/nstring.h"
#include "snetwork/NluEvent.h"
#include "snetwork/NluEventAccept.h"

namespace Sock
{
    CNluEventAccept *CNluEventAccept::m_instance = NULL;

    Threads::ThreadObject *CNluEventAccept::instance(void*)
    {
        if (m_instance==NULL) {
            m_instance = new CNluEventAccept();
        }
        return m_instance;
    }
    
    CNluEventAccept::CNluEventAccept()
    {
    
    }
    
    void CNluEventAccept::NewAccept(nlu_event_t *rev)
    {
        struct epoll_event ev;
        struct sockaddr in_addr;
        socklen_t in_len;
        int infd, s;
        char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
        in_len = sizeof in_addr;   
        nlu_connection_t *lc; 
        
        do {
            infd = accept (n_serverfd, &in_addr, &in_len);

            if (infd == -1)  {
                if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                    // We have processed all incoming connections. 
                    break;
                }
                else {
                    llog( "accept!\n" ); 
                    break;
                }               
            }

            s = getnameinfo (&in_addr, in_len,
                       hbuf, sizeof hbuf,
                       sbuf, sizeof sbuf,
                       NI_NUMERICHOST | NI_NUMERICSERV);
                       
            if (s == 0) {
                log("\n");
                llog("Accepted connection on descriptor %d "
                     "(host=%s, port=%s)", infd, hbuf, sbuf);
            }

            /* Make the incoming socket non-blocking and add it to the
             list of fds to monitor. */
            s = CNluEvent::instance()->setnonblocking(infd);

            if (s == -1) {
                llog( "set nonblocking error!\n" );
                abort ();
            }
            
            lc = rev->data;
            lc->fd = infd;

            ev.data.ptr = lc;
            ev.data.fd = infd;
            ev.events = EPOLLIN | EPOLLET;
            s = epoll_ctl (n_epfd, EPOLL_CTL_ADD, infd, &ev);

            if (s == -1) {
                llog( "epoll_ctl error\n" );
                abort ();
            }
            
        } while (true);
    }
    
    int CNluEventAccept::execute()
    {
         /* We have a notification on the listening socket, which
                 means one or more incoming connections. */        
        
        this->NewAccept();

        return 0; 
    }   
}    

